import { Vue, Component } from 'vue-property-decorator';
import style from './style.module.scss';
import { KBuilderAction, KBuilderColumn, KBuilderConfig, KBuilderResponse } from '@/components/k-builder/types/table';

@Component
export class KBuilderTable extends Vue {
    private config: KBuilderConfig = {};
    private data: any[] = [];
    private total: number = 0;
    private is_error: boolean = false;
    private error_msg: string = '';
    private page: number = 1;
    private search: any = {};
    private loading: boolean = true;
    private columns: KBuilderColumn[] = [];

    // 当前选择
    private selections: number[] = [];

    /**
     * 构建生命周期
     * @protected
     */
    protected build() {}


    /**
     * 接口前缀
     * @private
     */
    private get apiPrefix(): string {
        return this.config?.url?.prefix ?? 'admin/';
    }


    /**
     * 列
     */
    protected addColumn(col: KBuilderColumn) {
        this.columns.push(col);
        return this;
    }

    /**
     * 操作区按钮
     */
    protected get actions(): KBuilderAction[] {
        return [];
    }


    protected setConfig(config: KBuilderConfig) {
        this.config = Object.assign(this.config, config);
    }


    private created() {
        this.build();

        this.getListData();
    }

    private getListData() {
        if (!this.config?.url?.data) {
            this.loading = false;
            return;
        }
        this.$http.get(this.apiPrefix + this.config?.url?.data as string, {
            params: {
                page: this.page,
                limit: this.config.page?.limit,
                ...this.search,
            }
        }).finally(() => {
            this.loading = false;
        }).then(result => {
            if (!result.data?.items || !result.data?.total) {
                throw new Error(`列表接口 [${this.apiPrefix + this.config?.url?.data}] 返回格式有错`);
            }
            this.data = result.data.items;
            this.total = result.data.total;
        }).catch(err => {
            this.error_msg = err.message;
            this.is_error = true;
        })
    }


    private onPageChange(page: number) {
        this.page = page;
        this.loading = true;
        this.getListData();
    }

    /**
     * 搜索区构建 - 优先级最高,会覆盖内置的搜索框
     */
    protected searchBuilder(search: any, go: () => void) {
        return <div class={style.tableSearch}>
            <el-row>
                <el-col span={12}>
                    <el-button-group>
                        {this.config?.url?.add !== false ? <el-button type="primary" onClick={() => {
                            let url = this.config?.url?.add ?? (this.$route.fullPath + '/post');

                            this.$router.push({
                                path: '/' + url as string,
                                query: { id: '0' }
                            });
                        }}>添加</el-button> : ''}

                        <el-button type="danger" disabled={this.selections.length === 0} onClick={() => {
                            this.$confirm('确定要删除所选数据吗?')
                                .then(() => {
                                    this.deleteData(this.selections)
                                })
                                .catch(() => {})
                        }}>删除选中</el-button>

                        {this.config?.btns?.map(btn => <el-button onClick={btn.onClick}>
                            {btn.label}
                        </el-button>)}
                    </el-button-group>
                </el-col>

                <el-col span={12} style={{ textAlign: 'right' }}>
                    <el-form inline={true} nativeOn={
                        {
                            submit: (evt: any) => {
                                evt.preventDefault();
                                go();
                            }
                        }
                    }>
                        <el-form-item>
                            <el-input v-model={this.search.key} placeholder="输入关键字搜索" style={{ width: '400px' }}/>
                        </el-form-item>

                        <el-form-item>
                            <el-button type="info" icon="el-icon-search" native-type="submit">搜索</el-button>
                        </el-form-item>
                    </el-form>
                </el-col>
            </el-row>
        </div>
    }

    /**
     * 删除数据
     * @param ids
     * @private
     */
    private deleteData(ids: number[]) {
        let load = this.$loading({ text: '删除中...' })
        let url = this.config?.url?.delete ?? (this.$route.fullPath);
        this.$http.delete(this.apiPrefix + url as string, { data: { id: ids } })
            .finally(() => {
                load.close();
            })
            .then(() => {
                this.data = this.data.filter(item => !ids.includes(item.id));
                if (this.data.length <= (this.config?.page?.limit ?? 10) / 2) {
                    // 数据量少于一半时重新加载
                    this.getListData();
                }
                this.selections = [];
                this.$message.success('删除成功');
            })
    }

    render(h: any) {
        // 操作区
        let _actions = (props: any) => {
            let arr: any[] = [];

            if (this.config?.url?.edit !== false) {
                arr.push(<el-button type="info" onClick={() => {
                    let url = this.config?.url?.edit ?? (this.$route.fullPath + '/post');
                    this.$router.push({
                        path:  '/' + url as string,
                        query: {
                            id: props.row.id,
                        }
                    });
                }}>
                    编辑
                </el-button>)
            }

            if (this.config?.url?.delete !== false) {
                arr.push(<el-button type="danger" onClick={() => {

                    this.$confirm(`确定要删除ID:${props.row.id}的数据吗?`)
                        .then(() => {
                            this.deleteData([props.row.id]);
                        })
                        .catch(() => {})
                }}>
                    删除
                </el-button>)
            }
            return arr;
        }

        let action;
        if (this.actions.length || this.config?.url?.edit !== false || this.config?.url?.delete !== false) {
            action = <el-table-column label="操作" align="center" scopedSlots={{
                default: (props: any) => {
                    let obj: any = {
                        row: props.row,
                        update: (newData: any) => {
                            this.data.splice(props.$index, 1, { ...this.data[props.$index], ...newData })
                        },
                        delete: () => {
                            this.data.splice(props.$index, 1)
                        }
                    };
                    return [...this.actions.map(btn => (
                        <el-button type="text" onClick={() => btn.onClick && btn.onClick(obj)}>{btn.label}</el-button>
                    )), ..._actions(obj)]
                }
            }}/>;
        }

        return (
            <admin-container>
                {this.searchBuilder(this.search, () => {
                    this.loading = true;
                    this.page = 1;
                    this.data = [];
                    this.getListData();
                })}

                <el-table ref="table" data={this.data}
                          v-loading={this.loading}
                          row-key="id"
                          on-selection-change={(val: any[]) => {
                    this.selections = val.map(v => v.id);
                }}>
                    <el-table-column type="selection"/>

                    {this.columns.map(e => <el-table-column type={e.type}
                                                            width={e.width}
                                                            label={e.label}
                                                            scopedSlots={{
                                                                default: (props: any) => {
                                                                    if (typeof e.prop == 'string') {
                                                                        return (<div>{props.row[e.prop]}</div>)
                                                                    } else if (e.prop) {
                                                                        return e.prop(props.row);
                                                                    } else {
                                                                        return null;
                                                                    }
                                                                }
                                                            }}/>)}

                    {action}
                </el-table>

                <el-pagination current-page={this.page}
                               total={this.total}
                               hide-on-single-page={true}
                               layout="prev, pager, next, jumper, ->, total"
                               page-size={this.config.page?.limit}
                               on-current-change={(page: number) => this.onPageChange(page)}
                />
            </admin-container>
        )
    }
}
